package znet

import (
	"fmt"
	"net"
	"zinx/utils"
	"zinx/ziface"
)

type Server struct {
	Name      string
	IPVersion string
	IP        string
	Port      int
	// 消息管理模块， 用来绑定MsgID对应的处理业务API关系
	MsgHandler ziface.IMsgHandler

	ConnManager ziface.IConnManager

	// Server创建连接之前自动调用Hook函数--OnConnStart
	OnConnStart func(conn ziface.IConnection)
	// Server创建连接之后自动调用Hook函数--OnConnStop
	OnConnStop func(conn ziface.IConnection)
}

func NewServer(name string) *Server {
	return &Server{
		Name:        utils.GlobalObject.Name,
		IPVersion:   "tcp4",
		IP:          utils.GlobalObject.Host,
		Port:        utils.GlobalObject.TcpPort,
		MsgHandler:  NewMsgHandler(),
		ConnManager: NewConnManager(),
	}
}

func (s *Server) Start() {
	fmt.Println("[Start] server at IP: ", s.IP, " Port: ", s.Port, " is running...")

	go func() {
		// 开启消息队列 -- Worker工作池
		s.MsgHandler.StartWorkerPool()

		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			fmt.Println("resolve tcp error: ", err)
			return
		}

		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("listen tcp error: ", err)
			return
		}

		fmt.Println("Start Zinx server successfully, [", s.Name, "] listening...")
		var cid uint32
		cid = 0
		// 阻塞等待客户端连接，处理客户端连接业务(读写)
		for {
			// 如果有客户端连接过来阻塞返回
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("Accept error: ", err)
				continue
			}

			if s.ConnManager.Len() >= utils.GlobalObject.MaxConn {
				// TODO 给用户端响应一个错误
				fmt.Println("conn more than MaxConn: ", utils.GlobalObject.MaxConn)
				if err := conn.Close(); err != nil {
					return
				}
				continue
			}

			dealConn := NewConnect(s, conn, cid, s.MsgHandler)
			cid++

			go dealConn.Start()
		}
	}()
}

func (s *Server) Serve() {
	// 启动Server的服务功能
	s.Start()

	// TODO 做一些启动服务器之后的额外业务

	select {}
}

func (s *Server) Stop() {
	fmt.Println("[STOP] Zinx server name", s.Name)
	s.ConnManager.ClearConn()
}

func (s *Server) AddRouter(msgID uint32, router ziface.IRouter) {
	s.MsgHandler.AddRouter(msgID, router)
	fmt.Println("Add Router Successfully!")
}

func (s *Server) GetConnManger() ziface.IConnManager {
	return s.ConnManager
}

// SetOnConnStart 注册OnConnStart 钩子函数的方法
func (s *Server) SetOnConnStart(hookFunc func(connection ziface.IConnection)) {
	s.OnConnStart = hookFunc
}

// SetOnConnStop 注册OnConnStop 钩子函数的方法
func (s *Server) SetOnConnStop(hookFunc func(connection ziface.IConnection)) {
	s.OnConnStop = hookFunc
}

// CallOnConnStart 调用OnConnStart 钩子函数的方法
func (s *Server) CallOnConnStart(connection ziface.IConnection) {
	if s.OnConnStart != nil {
		fmt.Println("--> Call OnConnStart() ...")
		s.OnConnStart(connection)
	}
}

// CallOnConnStop 调用OnConnStop 钩子函数的方法
func (s *Server) CallOnConnStop(connection ziface.IConnection) {
	if s.OnConnStop != nil {
		fmt.Println("--> Call OnConnStop() ...")
		s.OnConnStop(connection)
	}
}
